package org.zcl.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.zcl.entity.model.ApiResponse;
import org.zcl.exception.BaseException;
import org.zcl.utils.ResponseUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ValidationException;
import java.util.stream.Collectors;

@RestControllerAdvice
@Slf4j
public class GlobalControllerAdvice {

    private static final String ERROR_CODE_COMMON = "-1";
    private static final String ERROR_MSG_COMMON = "哎呀，服务出错了";
    private static final String ERROR_PARAM_COMMON = "参数不正确，请检查";

    @ExceptionHandler(IllegalArgumentException.class)
    public ApiResponse<?> processException(HttpServletRequest request, HttpServletResponse response, IllegalArgumentException e) {
        log.error("params exception occurs, request:{}", request.getRequestURL(), e);
        ResponseUtils.setNoCache(response);
        ApiResponse<?> result = new ApiResponse<>();
        result.setCode(ERROR_CODE_COMMON);
        result.setErrMsg(e.getMessage());
        result.setMsg(ERROR_PARAM_COMMON);
        return result;
    }

    @ExceptionHandler(BaseException.class)
    public ApiResponse<?> processException(HttpServletRequest request, HttpServletResponse response, BaseException e) {
        log.warn("base exception occurs, request:{}", request.getRequestURL(), e);
        ResponseUtils.setNoCache(response);
        ApiResponse<?> result = new ApiResponse<>();
        result.setCode(e.getCode());
        result.setErrMsg(e.getMessage());
        return result;
    }

    @ExceptionHandler(ValidationException.class)
    public ApiResponse<?> processException(HttpServletRequest request, HttpServletResponse response, ValidationException e) {
        log.warn("base exception occurs, request:{}", request.getRequestURL(), e);
        ResponseUtils.setNoCache(response);
        ApiResponse<?> result = new ApiResponse<>();
        result.setCode(ERROR_CODE_COMMON);
        result.setErrMsg(e.getMessage());
        return result;
    }
    @ExceptionHandler(HttpMessageConversionException.class)
    public ApiResponse<?> processException(HttpServletRequest request, HttpServletResponse response, HttpMessageConversionException e) {
        log.error("http message exception occurs, request:{}", request.getRequestURL(), e);
        ResponseUtils.setNoCache(response);
        ApiResponse<?> result = new ApiResponse<>();
        result.setCode(ERROR_CODE_COMMON);
        result.setErrMsg(ERROR_PARAM_COMMON);
        return result;
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ApiResponse<?> processException(HttpServletRequest request, HttpServletResponse response, MethodArgumentNotValidException e) {
        log.error("http message exception occurs, request:{}", request.getRequestURL(), e);
        ResponseUtils.setNoCache(response);
        ApiResponse<?> result = new ApiResponse<>();
        result.setCode(ERROR_CODE_COMMON);
        result.setErrMsg(e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(",")));
        return result;
    }

    @ExceptionHandler(BindException.class)
    public ApiResponse<?> processException(HttpServletRequest request, HttpServletResponse response, BindException e) {
        log.error("binding params exception occurs, request:{}", request.getRequestURL(), e);
        ResponseUtils.setNoCache(response);
        ApiResponse<?> result = new ApiResponse<>();
        result.setCode(ERROR_CODE_COMMON);
        result.setErrMsg(e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(",")));
        return result;
    }

    @ExceptionHandler(Exception.class)
    public ApiResponse<?> processException(HttpServletRequest request, HttpServletResponse response, Exception e) {
        log.error("exception occurs, request:{}", request.getRequestURL(), e);
        ResponseUtils.setNoCache(response);
        ApiResponse<?> result = new ApiResponse<>();
        result.setCode(ERROR_CODE_COMMON);
        result.setErrMsg(ERROR_MSG_COMMON);
        return result;
    }

    @ExceptionHandler(Throwable.class)
    public ApiResponse<?> processException(HttpServletRequest request, HttpServletResponse response, Throwable e) {
        log.error("throwable error, request:{}", request.getRequestURL(), e);
        ResponseUtils.setNoCache(response);
        ApiResponse<?> result = new ApiResponse<>();
        result.setCode(ERROR_CODE_COMMON);
        result.setErrMsg(ERROR_MSG_COMMON);
        return result;
    }
}
